<?php
declare(strict_types=1);

namespace App\Common\Extend\Ai\Model;

use App\Sys;
use Swoole\Coroutine\Http\Client;
use Zms\Unit\Is;
use Zms\Unit\Json;
/**
 * @document https://platform.deepseek.com/usage
 */
class DeepSeek
{
    /**
     * Ai对话
     * @param string $message
     * @param callable $callback
     * @return void
     */
    public function chat(string $message, callable $callback): void
    {
        $client = new Client('api.deepseek.com', 443, true);
        $client->setHeaders([
            'Content-Type' => ' application/json',
            'Authorization' => ' Bearer ' . $this->getKey()
        ]);
        // 准备请求数据
        $client->setMethod('POST');
        $client->setData(json_encode([
            'model' => 'deepseek-chat',
            'messages' => [
                ['role' => 'user', 'content' => $message]
            ],
            'stream' => true,
            'max_tokens' => 2048,
            'temperature' => 0.7,
            'top_p' => 0.7,
            'top_k' => 50,
            'frequency_penalty' => 0.5,
            'n' => 1,
            'response_format' => [
                'type' => 'text'
            ]
        ]));
        $client->set(['timeout' => -1, 'stream' => true]); // 设置超时时间
        $client->set(['write_func' => function ($client, $data) use ($callback) {
            if (Is::json($data)) {
                $result = Json::decode($data);
                if (isset($result['error'])) {
                    $callback("访问失败:" . $result['error']['message'] ?? '请求失败');
                }
                $client->close();
            } else {
                if (str_contains($data, "[DONE]")) {
                    $callback(null);
                    $client->close();
                } else {
                    $result = $this->handleStreamChunk($data);
                    if ($result) {
                        $callback($result);
                    }
                }
            }
        }]);
        $client->execute('/chat/completions');
    }

    public function getKey(): mixed
    {
        return Sys::conf('ai.deepseek_key') ?? '';
    }


    /**
     * 处理数据块的函数
     * @param $chunk
     * @return string
     */
    public function handleStreamChunk($chunk): string
    {
        $lines = explode("\n", trim($chunk));
        $string = '';
        foreach ($lines as $line) {
            if (trim($line) === '' || $line === 'data: [DONE]') continue;
            if (str_starts_with($line, 'data: ')) {
                $jsonStr = substr($line, 6); // 去除 "data: " 前缀
                $data = json_decode($jsonStr, true);
                $string .= $data['choices'][0]['delta']['content'] ?? '';
            }
        }
        return $string;
    }
}